001 package net.sf.xdc.processing;
002
003 /*
004 * Copyright 2005-2006 Jens Voß.
005 *
006 * Licensed under the GNU Lesser General Public License (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://opensource.org/licenses/lgpl-license.php
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 import java.io.File;
020 import java.io.FileInputStream;
021 import java.io.InputStream;
022 import java.io.IOException;
023 import java.io.FileNotFoundException;
024 import java.io.BufferedReader;
025 import java.io.FileReader;
026 import java.util.Map;
027 import java.util.Properties;
028 import java.util.Enumeration;
029 import java.util.HashMap;
030 import java.util.LinkedHashMap;
031 import java.util.StringTokenizer;
032 import java.util.Iterator;
033 import java.util.regex.Pattern;
034
035 import org.apache.commons.cli.CommandLine;
036 import org.apache.log4j.Logger;
037 import net.sf.xdc.util.Logging;
038 import net.sf.xdc.util.PathDescriptor;
039
040 /**
041 * This class is used for determining the XML dialect of an input XML file in
042 * order to be able to apply the correct XSLT stylesheet to the input file.
043 *
044 * @author Jens Voß
045 * @since 0.5
046 * @version 0.5
047 */
048 public class DialectHandler {
049
050 private static final Logger LOG = Logging.getLogger();
051
052 private static final String XSL_PACKAGE = "net/sf/xdc/xsl";
053 private static final Map DEFAULTS = new HashMap();
054 private static final Map MAPPINGS = new LinkedHashMap();
055 private static boolean initialized = false;
056
057 static {
058 DEFAULTS.put("generic", new DialectHandler("generic", XSL_PACKAGE + "/generic.xsl"));
059 DEFAULTS.put("xsl", new DialectHandler("xsl", XSL_PACKAGE + "/xsl.xsl"));
060 DEFAULTS.put("ant", new DialectHandler("ant", XSL_PACKAGE + "/ant.xsl"));
061 }
062
063 private static void init(CommandLine commandLine) {
064 Properties props = new Properties();
065 if (commandLine.hasOption("dialects")) {
066 InputStream in = null;
067 try {
068 in = new FileInputStream(commandLine.getOptionValue("dialects"));
069 props.load(in);
070 for (Enumeration keys = props.keys(); keys.hasMoreElements();) {
071 String key = (String) keys.nextElement();
072 DEFAULTS.put(key, new DialectHandler(key, props.getProperty(key)));
073 }
074 }
075 catch (FileNotFoundException e) {
076 LOG.error(e.getMessage(), e);
077 }
078 catch (IOException e) {
079 LOG.error(e.getMessage(), e);
080 }
081 finally {
082 try {
083 if (in != null) {
084 in.close();
085 }
086 }
087 catch (IOException e) {
088 LOG.error(e);
089 }
090 }
091 }
092 if (commandLine.hasOption("dialectmapping")) {
093 BufferedReader in = null;
094 try {
095 in = new BufferedReader (new FileReader(commandLine.getOptionValue("dialectmapping")));
096 for (String line = in.readLine(); line != null; line = in.readLine()) {
097 StringTokenizer tok = new StringTokenizer(line, "=", false);
098 MAPPINGS.put(PathDescriptor.convert(tok.nextToken().trim()),
099 tok.nextToken().trim());
100
101 }
102 }
103 catch (IOException e) {
104 LOG.error(e.getMessage(), e);
105 }
106 finally {
107 try {
108 if (in != null) {
109 in.close();
110 }
111 }
112 catch (IOException e) {
113 e.printStackTrace();
114 }
115 }
116 }
117 initialized = true;
118 }
119
120 /**
121 * Static getter method for the correct DialectHandler object.
122 *
123 * @param file The input file for which the correct DialectHandler is
124 * retrieved
125 * @param packageName
126 * @param commandLine The CommandLine object which may contain additional
127 * elements controlling which DialectHandler to return
128 * @return The correct DialectHandler for the input file depending on the
129 * command line settings
130 */
131 public static DialectHandler getDialectHandler(File file,
132 String packageName,
133 CommandLine commandLine) {
134 if (!initialized) {
135 init(commandLine);
136 }
137 String name = getDialect(file, packageName, commandLine);
138 DialectHandler retVal = (DialectHandler) DEFAULTS.get(name);
139 return retVal == null ? (DialectHandler) DEFAULTS.get("generic") : retVal;
140 }
141
142 private static String getDialect(File file, String packageName,
143 CommandLine commandLine) {
144 String filename = packageName != null && packageName.length() != 0 ?
145 packageName + '/' + file.getName() : file.getName();
146 // check the defined dialectmappings first
147 for (Iterator keys = MAPPINGS.keySet().iterator(); keys.hasNext();) {
148 String regex = (String) keys.next();
149 if (Pattern.matches(regex, filename)) {
150 return (String) MAPPINGS.get(regex);
151 }
152 }
153 // then use the predefined dialect
154 if (commandLine.hasOption("dialect")) {
155 return commandLine.getOptionValue("dialect");
156 }
157 // next try the defaults
158 if ("build.xml".equals(file.getName())) {
159 return "ant";
160 }
161 if (file.getName().endsWith(".xsl")) {
162 return "xsl";
163 }
164 // otherwise
165 return "generic";
166 }
167
168 private String name;
169 private String xslResourcePath;
170
171 /**
172 * Protected constructor. Invoked in static initializer of this class.
173 *
174 * @param name The name of this <code>DialectHandler</code>
175 * @param xslPath The relative path (within the classpath) of this
176 * <code>DialectHandler</code>
177 */
178 protected DialectHandler(String name, String xslPath) {
179 this.name = name;
180 this.xslResourcePath = xslPath;
181 }
182
183 /**
184 * Getter method for this <code>DialectHandler</code>'s name.
185 *
186 * @return The name of this <code>DialectHandler</code>
187 */
188 public String getName() {
189 return name;
190 }
191
192 /**
193 * Getter method for this <code>DialectHandler</code>'s resource path.
194 *
195 * @return The resource path of this <code>DialectHandler</code>
196 */
197 public String getXslResourcePath() {
198 return xslResourcePath;
199 }
200
201 }